<?php
/**
 * Created by PhpStorm.
 * User: wuxiansheng
 * Date: 2018/8/5
 * Time: 下午5:46
 */

namespace App\Console\Service;

use Illuminate\Support\Facades\Redis;
use App\Libs\Runtime;
use App\Article;

class ZhihuService
{

    public $zhihuApi = [
        "before" => "https://news-at.zhihu.com/api/4/news/before/%s"
    ];

    /*
     * 获取列表生成任务
     */
    public function makeData()
    {
        $runtime= new runtime;
        $runtime->start();

        //删除合集
        Redis::del("itemSet");

        //获取今天开始的日期
        $dateArr = [];
        $year = 365 * 7;
        //$year = 50;
        for ($i = 1; $i < $year; $i++) {
            $dateItem = date("Ymd", strtotime("-$i day"));
            $dateArr[] = $dateItem;
        }

        //创建过程
        $worker_num = 10;
        $process_pool = [];
        $process = null;
        $customMsgKey = 1;
        $mod = 2 | \swoole_process::IPC_NOWAIT;//这里设置消息队列为非阻塞模式

        //创建worker进程
        for ($i = 0; $i < $worker_num; $i++) {
            $process = new \swoole_process(function (\swoole_process $worker) {
                sleep(1); //防止父进程还未往消息队列中加入内容直接退出
                echo "worker " . $worker->pid . " started" . PHP_EOL;
                while ($msg = $worker->pop()) {
                    sleep(1);
                    if ($msg === false) {
                        break;
                    }
                    $sub_pid = $worker->pid;
                    echo "[$sub_pid] msg : $msg" . PHP_EOL;

                    //执行任务
                    $url = $this->createUrl($msg);
                    echo $url.PHP_EOL;
                    try {
                        $curl = new \Curl\Curl();
                        $curl->get($url);
                        $result = json_decode($curl->response);
                        foreach ($result->stories as $item) {
                            Redis::lpush("itemSet", json_encode($item));
                        };
                        echo "[$sub_pid] msg : insert success" . PHP_EOL;
                    } catch (\Exception $e) {
                        //echo $e;
                        echo "[$sub_pid] msg : insert error" . PHP_EOL;
                    }
                    sleep(1);
                }
                echo "worker " . $worker->pid . " exit" . PHP_EOL;
                $worker->exit(0);
            });
            $process->useQueue($customMsgKey, $mod);
            $process->start();
            $pid = $process->pid;
            $process_pool[$pid] = $process;
        }

        //由于所有进程是共享使用一个消息队列，所以只需向一个子进程发送消息即可
        $process = current($process_pool);
        foreach ($dateArr as $msg) {
            $process->push($msg);
        }

        //子进程结束必须要执行wait进行回收，否则子进程会变成僵尸进程
        while ($ret = \swoole_process::wait()) {// $ret 是个数组 code是进程退出状态码，
            $pid = $ret['pid'];
            echo "Worker Exit, PID=" . $pid . PHP_EOL;
        }
        echo "Master exit" . PHP_EOL;

        //记录执行时间
        $runtime->stop();
        $spent_time = $runtime->spent($echo=true, '');
        $runtime->clear();

    }

    //创建URL链接
    private function createUrl($date)
    {
        return empty($date) ? "" : sprintf($this->zhihuApi["before"], $date);
    }

    public function saveData(){

        $runtime= new runtime;
        $runtime->start();
        $worker_num = 5;

        //创建worker进程
        for ($i = 0; $i < $worker_num; $i++) {
            $process = new \swoole_process(function (\swoole_process $worker) {
                sleep(1);
                echo "worker " . $worker->pid . " started" . PHP_EOL;
                $msg = true;
                while ($msg) {
                    $item = Redis::rpop("itemSet");
                    if (!empty($item)) {
                        try {
                            $item = json_decode($item);
                            $data = [
                                "id" => $item->id,
                                "title" => $item->title,
                                "type" => $item->type,
                                "images" => $item->images[0],
                                "ga_prefix" => $item->ga_prefix
                            ];
                            $model = Article::create($data);
                            if($model){
                                echo "Worker Success, PID=" . $worker->pid . PHP_EOL;
                            }else{
                                echo "Worker Error, PID=" . $worker->pid . PHP_EOL;
                            }
                        } catch(\Exception $e) {
                            echo "Worker Error, PID=" . $worker->pid . PHP_EOL;
                        }
                    }else{
                        $msg = false;
                        break;
                    }
                }
            });
            $process->start();
            $pid = $process->pid;
            $process_pool[$pid] = $process;
        }

        //子进程结束必须要执行wait进行回收，否则子进程会变成僵尸进程
        while ($ret = \swoole_process::wait()) {// $ret 是个数组 code是进程退出状态码，
            $pid = $ret['pid'];
            echo "Worker Exit, PID=" . $pid . PHP_EOL;
        }

        echo "save data end!". PHP_EOL;

        //记录执行时间
        $runtime->stop();
        $spent_time = $runtime->spent($echo=true, '');
        $runtime->clear();
    }
}